home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 5366 < prev    next >
Encoding:
Text File  |  1996-08-05  |  5.5 KB  |  158 lines

  1. Path: duck.ibh-dd.de!beck
  2. From: beck@duck.ibh-dd.de (Andre Beck)
  3. Newsgroups: comp.lang.c
  4. Subject: Who's dumb: me or my compiler ?
  5. Followup-To: poster
  6. Date: 12 Feb 1996 15:31:57 GMT
  7. Organization: IBH - Xlink PoP Dresden
  8. Message-ID: <4fnmhd$c1o@micky.ibh-dd.de>
  9. NNTP-Posting-Host: duck.ibh-dd.de
  10. X-Newsreader: TIN [version 1.2 PL1]
  11.  
  12. Hi,
  13.  
  14. I could have had a really bad day searching for this bug, but for
  15. some lucky circumstances, I trapped it instantly. However I don't
  16. know whether I wrote bad code or whether a number of compilers do
  17. it wrong in the same way - the latter doesn't sound that probable ;)
  18.  
  19. My problem turns around the expression
  20.  
  21.  x = (*ptr++ << 8) | *ptr++;
  22.  
  23. which is pretty simple (IMHO). Read two subsequent bytes from memory
  24. and make a word off them. Not nice, I know, even endian-dependant. But
  25. nothing to fail on. Now, GCC fails on 3 different platforms, and DEC
  26. cc for Ultrix fails as well. Here's my trigger program:
  27.  
  28. ------------------------- snip -------------------------
  29. /*
  30.  
  31. This program produces an IMHO wrong result on a number of compilers and
  32. different architectures. Either I don't understand C correctly, or several
  33. compilers (including GNU C) optimize an expression containing two invo-
  34. cations of an autoincrementing pointer dereference into one dereference,
  35. treating the dereference as a common subexpression (which it isn't as it
  36. has a side effect).
  37.  
  38. */
  39.  
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42.  
  43. void f(const unsigned char *pkt)
  44. {
  45.  const unsigned char *dat = pkt;
  46.  unsigned short proto;
  47.  
  48.  /* The intention is to read a word at an probably odd address in an
  49.     endian dependent way
  50.  */
  51.  proto = (*dat++ << 8) | *dat++;
  52.  
  53.  printf("%04x\n", proto);
  54. }
  55.  
  56. /*
  57.  
  58. Disassembly of optimized function f on a SPARC 10 looks like:
  59.  
  60. section .text
  61. f()
  62.         10794:  9d e3 bf 90        save         %sp, -112, %sp
  63.         10798:  d2 0e 00 00        ldub         [%i0], %o1
  64.                                    ^^^^^^^^^^^^^^^^^^^^^^^
  65.                                    Loads the first byte from pointer
  66.  
  67.         1079c:  11 00 00 42        sethi        %hi(0x10800), %o0
  68.         107a0:  90 12 20 e8        or           %o0, 232, %o0
  69.         107a4:  95 2a 60 08        sll          %o1, 8, %o2
  70.                                    ^^^^^^^^^^^^^^^^^^^^^^^^
  71.                                    Shiftleft of this value is Ok
  72.  
  73.         107a8:  40 00 40 8a        call         printf
  74.         107ac:  92 12 40 0a        or           %o1, %o2, %o1
  75.                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  76.                                    The OR would be Ok, but %o1 was never
  77.                                    fetched from memory, it's just reused.
  78.                                    Is the optimizer taking *dat++ for a
  79.                                    common subexpression (which it isn't) ?
  80.  
  81.         107b0:  81 c7 e0 08        ret    
  82.         107b4:  81 e8 00 00        restore
  83. */
  84.  
  85. /*
  86.  
  87. Disassembly on a MIPS reveals the exactly same behavior:
  88.  
  89.         f:
  90.   [gccbug.c:  88] 0x4001b0:     27bdffe8        addiu   sp,sp,-24
  91.   [gccbug.c:  87] 0x4001b4:     afbf0010        sw      ra,16(sp)
  92.   [gccbug.c:  87] 0x4001b8:     90850000        lbu     a1,0(a0)
  93.                                                 ^^^^^^^^^^^^^^^^
  94.                                                 Fetch the first byte
  95.  
  96.   [gccbug.c:  89] 0x4001bc:     27848010        addiu   a0,gp,-32752
  97.   [gccbug.c:  95] 0x4001c0:     00051200        sll     v0,a1,8
  98.   [gccbug.c:  90] 0x4001c4:     0c10013c        jal     printf
  99.   [gccbug.c:  91] 0x4001c8:     00a22825        or      a1,a1,v0
  100.                                                 ^^^^^^^^^^^^^^^^
  101.                                                 Seems v0 is treatened as a
  102.                                                 common subexpression
  103.  
  104.   [gccbug.c: 120] 0x4001cc:     8fbf0010        lw      ra,16(sp)
  105.   [gccbug.c:  92] 0x4001d0:     27bd0018        addiu   sp,sp,24
  106.   [gccbug.c:  96] 0x4001d4:     03e00008        jr      ra
  107.   [gccbug.c:  93] 0x4001d8:     00000000        nop
  108.  
  109. */
  110.  
  111. /*
  112.  
  113. And now the Dessert: x86 code as generated on Linux. Here the Bug
  114. triggers even when not optimizing at all. Probably this processor has
  115. not enough registers to allow a compiler to _not_ optimize...
  116.  
  117. 00001088 <_f> pushl  %ebp
  118. 00001089 <_f+1> movl   %esp,%ebp
  119. 0000108b <_f+3> movl   0x8(%ebp),%eax
  120. 0000108e <_f+6> movzbw (%eax),%dx       ; fetching first byte
  121. 00001092 <_f+a> movl   %edx,%eax
  122. 00001094 <_f+c> shlw   $0x8,%ax         ; shifting it up
  123. 00001098 <_f+10> orw    %dx,%ax         ; and never fetching the second one
  124. 0000109b <_f+13> andl   $0xffff,%eax
  125. 000010a0 <_f+18> pushl  %eax
  126. 000010a1 <_f+19> pushl  $0x1078
  127. 000010a6 <_f+1e> call   60000a00 <_printf>
  128. 000010ab <_f+23> movl   %ebp,%esp
  129. 000010ad <_f+25> popl   %ebp
  130. 000010ae <_f+26> ret    
  131.  
  132. int main()
  133. {
  134.  unsigned short bla = 0x6622;
  135.  unsigned char *buf = (unsigned char *) &bla;
  136.  
  137.  printf("This program should generate either 6622 or 2266 as output:\n");
  138.  
  139.  f(buf);
  140.  
  141.  return(0);
  142. }
  143. ---------------------------- snap -----------------------------
  144.  
  145. If anyone out there can tell me what's wrong here, I would be pleased.
  146. Please answer by email, I dont have enough time to follow this high
  147. traffic group in detail. Instead, I'll post a summary if it makes any
  148. sense.
  149.  
  150. Thanks,
  151. Andre.
  152. --
  153. +-o-+--------------------------------------------------------+-o-+
  154. | o |               \\\- Brain Inside -///                   | o |
  155. | o |                   ^^^^^^^^^^^^^^                       | o |
  156. | o | Andre' Beck (ABPSoft) beck@ibh-dd.de XLink PoP Dresden | o |
  157. +-o-+--------------------------------------------------------+-o-+
  158.